
// 订阅者回调签名
typedef void EventCallBack(args);

class EventBus {

  // 私有构造函数
  EventBus._internal();
  // 保存单例
  static final EventBus _singleton = EventBus._internal();
  // 工厂构造函数
  factory EventBus() => _singleton;
  //  保存事件订阅者队列, key:事件名(id)，value:对应事件的订阅者队列
  final _emap = Map<Object, List<EventCallBack>?>();

  // 添加订阅者
  void on(eventName, EventCallBack f) {
    _emap[eventName] ??= <EventCallBack>[];
    _emap[eventName]!.add(f);
  }

  //  移除订阅者
  void off(eventName, [EventCallBack? f]) {
    var list = _emap[eventName];
    if (eventName == null || list == null) return;
    if (f == null) {
      _emap[eventName] = null;
    } else {
      list.remove(f);
    }
  }


  // 触发事件，事件触发后该事件所有订阅者会被调用
  void emit(eventName, [args]) {
    var list = _emap[eventName];
    if (list == null) return;
    int len = list.length - 1;
    // 反向遍历，防止订阅者在回调中移除自身导致下标越界
    for (var i = len; i > -1; --i) {
      list[i](args);
    }
  }

  void test() {
    EventBus? bus = EventBus();
    Object? userInfo;
    //页面A中
    // ...
    //监听登录事件
    bus.on("login", (arg) {
    // do something
    });

    //登录页B中
    //     ...
    //登录成功后触发登录事件，页面A中订阅者会被调用
     bus.emit("login", userInfo);
  }

}